/**
 * Узел дерева, который не изменяется со временем, т.к. переменная height при создании
 * дерева используется по назначению, а после создания как id.
 * 
 * Словарь НЕ может пополняться после загрузки, т.к. информация о height не сохраняется.
 * Чтобы разрешить модификацию после загрузки надо для id выделить отдельную переменную
 * и ее использовать в getId() и setId() (т.е. их переопределить)
 */
public class Node<T> implements Comparable<Node<T>> {
    Word key;
    T value;

    /*
     * При построении дерева height - это высота узла в дереве. Для сохраненного в файл дерева или
     * загруженного из файла - это id (уникальной номер узла). Дерево не предназначено
     * для модификации после сохранения в файл или загрузки из файла. Если
     * потребуется менять дерево после файловых операций, то
     * для id надо выделить отдельную переменну.
     */
    int height = 1; // New nodes are added at leaf.
    Object left = null; // Node или Integer, второй только на этапе загрузки из файла
    Object right = null; // Node или Integer, второй только на этапе загрузки из файла
    
    Node(final Word key, final T value) {
        this.key = key;
        this.value = value;
    }

    @SuppressWarnings("unchecked")
    final Node<T> left() {
        return (Node<T>) left;
    }

    @SuppressWarnings("unchecked")
    final Node<T> right() {
        return (Node<T>) right;
    }

    final int getId() {
        return height;
    }

    final void setId(final int id) {
        this.height = id;
    }

    final int balance() {
        return ((left != null) ? left().height : 0) - ((right != null) ? right().height : 0);
    }

    final void height() {
        height = Math.max(((left != null) ? left().height : 0), ((right != null) ? right().height : 0)) + 1;
    }

    @Override
    final public int compareTo(Node<T> o) {
        final int x = getId();
        final int y = o.getId();
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }
}
